package com.smsc.headend.task.engine.ftp.config;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.extra.ftp.AbstractFtp;
import cn.hutool.extra.ftp.Ftp;
import cn.hutool.extra.ssh.Sftp;
import com.jcraft.jsch.SftpException;
import com.smsc.headend.common.constant.Constant;
import com.smsc.headend.common.utils.DesEncrypt;
import com.smsc.headend.task.engine.service.FeignAssetManagementService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * @author qinbin
 */
@Slf4j
@Component
public class SftpUtils {

    private static final String FTP = "FTP";

    @Autowired
    FeignAssetManagementService feignAssetManagementService;

    /**
     * 批量上传文件
     *
     * @param localPath
     * @param remotePath
     * @param remotePathCsv
     * @param sftpConfig
     * @throws SftpException
     */
    public void upLoadFiles(String localPath, String remotePath, String remotePathCsv, SftpConfig sftpConfig) throws SftpException, IOException {
        //查找当前上传时间前5s（过滤掉少部分正在写的文件）,且文件名不以.bak结尾的文件
        List<File> files = FileUtil.loopFiles(localPath, pathname -> !pathname.toString().endsWith(".bak") && pathname.lastModified() < System.currentTimeMillis() - 5000);
        if (CollUtil.isEmpty(files)) {
            log.info("there are no files to upload,{}", localPath);
            return;
        }
        String csv = feignAssetManagementService.getPropertyValue("DDS_CSV_SWITCH");
        String ftpType = feignAssetManagementService.getPropertyValue("DDS_FTP_TYPE");
        String hostName = feignAssetManagementService.getPropertyValue("DDS_SFTP_HOSTNAME");
        String port = feignAssetManagementService.getPropertyValue("DDS_SFTP_PORT");
        String username = feignAssetManagementService.getPropertyValue("DDS_SFTP_USERNAME");
        String password = feignAssetManagementService.getPropertyValue("DDS_SFTP_PASSWORD");
        AbstractFtp ftp = null;
        if (CharSequenceUtil.isAllBlank(hostName, port, username, password)) {
            hostName = sftpConfig.getHostName();
            port = String.valueOf(sftpConfig.getPort());
            username = sftpConfig.getUsername();
            password = sftpConfig.getPassword();
        }
        DesEncrypt des = new DesEncrypt();
        if (CharSequenceUtil.isNotEmpty(password)) {
            password = des.getDesString(password);
        }
        try {
            if (FTP.equals(ftpType)) {
                ftp = new Ftp(hostName, Convert.toInt(port), username, password);
            } else {
                ftp = new Sftp(hostName, Convert.toInt(port), username, password);
            }
            for (File file : files) {
                try {
                    if (file.getName().toLowerCase().endsWith(".txt")) {
                        log.info("start upload file {},remotePath={}", file.getName(), remotePath);
                        boolean upload = ftp.upload(remotePath, file);
                        if (upload) {
                            log.info("file upload successful {}", file.getName());
                            // bak
                            String bakPath = file.getParent() + "/dds_path/" + file.getName();
                            bakPath = bakPath.replace(".txt", ".bak");
                            FileUtil.move(file, FileUtil.file(bakPath), true);
                            log.info("file backup successful", file.getName());
                        } else {
                            log.error("file upload failed {}", file.getName());
                        }
                    }
                    if (CharSequenceUtil.equalsIgnoreCase(csv, Constant.TRUE) && file.getName().toLowerCase().endsWith(".csv")) {
                        log.info("start upload file {},remotePathCsv={}", file.getName(), remotePathCsv);
                        boolean upload = ftp.upload(remotePathCsv, file);
                        if (upload) {
                            log.info("file upload successful {}", file.getName());
                            // bak
                            String bakPath = file.getParent() + "/dds_path/" + file.getName();
                            bakPath = bakPath.replace(".csv", ".bak");
                            FileUtil.move(file, FileUtil.file(bakPath), true);
                            log.info("file backup successful", file.getName());
                        } else {
                            log.error("file upload failed {}", file.getName());
                        }
                    }

                } catch (Exception e2) {
                    log.error("file upload failed {} exception {}", file.getName(), e2.getMessage());
                }
            }
        } catch (Exception e) {
            log.error("file connect failed exception {}", e.getMessage());
        } finally {
            if (null != ftp) {
                ftp.close();
            }
        }
    }

    /**
     * 上传单个文件至SFTP，用于DDS本地产生文件之后直接写入
     *
     * @param remotePath
     * @param sftpConfig
     * @param file
     * @param localBackUpPath
     * @throws SftpException
     */
    public void upLoadSingleFile(String remotePath, SftpConfig sftpConfig, File file, String localBackUpPath) throws SftpException, IOException {
        log.info("start to upload file to the server, the file name : {}", file.getName());
        String ftpType = feignAssetManagementService.getPropertyValue("DDS_FTP_TYPE");
        String hostName = feignAssetManagementService.getPropertyValue("DDS_SFTP_HOSTNAME");
        String port = feignAssetManagementService.getPropertyValue("DDS_SFTP_PORT");
        String username = feignAssetManagementService.getPropertyValue("DDS_SFTP_USERNAME");
        String password = feignAssetManagementService.getPropertyValue("DDS_SFTP_PASSWORD");
        AbstractFtp ftp = null;
        if (CharSequenceUtil.isAllBlank(hostName, port, username, password)) {
            hostName = sftpConfig.getHostName();
            port = String.valueOf(sftpConfig.getPort());
            username = sftpConfig.getUsername();
            password = sftpConfig.getPassword();
        }
        DesEncrypt des = new DesEncrypt();
        if (CharSequenceUtil.isNotEmpty(password)) {
            password = des.getDesString(password);
        }
        try {
            if (FTP.equals(ftpType)) {
                ftp = new Ftp(hostName, Convert.toInt(port), username, password);
            } else {
                ftp = new Sftp(hostName, Convert.toInt(port), username, password);
            }
            log.info("{} connect success host:{},port:{},username:{}", ftpType, hostName, port, username);
            boolean upload = ftp.upload(remotePath, file);
            if (upload) {
                log.info("file upload successful {}", file.getName());
                // bak
                FileUtil.move(file, FileUtil.file(localBackUpPath), true);
                log.info("file backup successful", file.getName());
            } else {
                log.error("file upload failed {}", file.getName());
            }
        } catch (Exception e) {
            log.error("file {} upload failed! message:{}", file.getName(), e.getMessage());
        } finally {
            try {
                if (null != ftp) {
                    ftp.close();
                }
            } catch (IOException e) {
                log.error("close {} connect error", ftpType);
            }
        }


    }
}

